using System;
using NUnit.Framework;
using TDUnit.Common.TestData;
using TDUnit.MsSql;

namespace TDUnit.Tests
{
    [TestFixture]
    public class BasicSqlScriptEngineTests
    {
        readonly BasicSqlScriptEngine scriptEngine = new BasicSqlScriptEngine();

        #region Insert Script Tests

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CreateInsertStatementWithNullRowThrowsException()
        {
            scriptEngine.GetInsertScriptForRow(null);
        }

        [Test]
        public void CreateInsertStatementWithOnlyPrimaryKeyColumnNotQuoted()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([PKColumn]) VALUES (1);";
            var row = CreateRow();

            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateInsertStatementWithOnlyPrimaryKeyColumnQuoted()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([PKColumn]) VALUES ('1');";
            var row = CreateRow();
            row.PrimaryKeyColumn.WithShouldQuote(true);

            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateSimpleInsertStatement()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([Numeric],[ID]) VALUES (2,1);";
            var row = CreateRow("ID", "1");
            row.AddColumn("Numeric").WithValue("2");
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateQuotedInsertStatement()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([String],[ID]) VALUES ('Value',1);";
            var row = CreateRow("ID", "1");
            row.AddColumn("String").WithValue("Value").WithShouldQuote(true);
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateInsertStringWithAutoIdentityPrimaryKeyShouldNotAddPrimaryKeyToListOfValues()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([ColumnOne]) VALUES ('Value');";
            var row = CreateRow("ID", "");
            row.PrimaryKeyColumn.WithIsAutoIdentity(true);
            row.AddColumn("ColumnOne").WithValue("Value");
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateInsertStatementWithEmptyStringValue()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([String],[ID]) VALUES ('',1);";

            var row = CreateRow("ID", "1");
            row.AddColumn("String").WithValue("");
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateInsertStatementWithNullValue()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([String],[ID]) VALUES (NULL,1);";
            var row = CreateRow("ID", "1");
            row.AddColumn("String").WithValue("NULL");
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        [Test]
        public void CreateInsertStatementWithSingleQuotesInVaule()
        {
            const string expectedStatement = "INSERT INTO [TableName] ([String],[ID]) VALUES ('String''s Value',1);";
            var row = CreateRow("ID", "1");
            row.AddColumn("String").WithValue("String's Value");
            Assert.AreEqual(expectedStatement, scriptEngine.GetInsertScriptForRow(row));
        }

        #endregion

        #region AutoIdentity tests

        [Test]
        public void GetAutoIdentitySelectScript()
        {
            const string expectScript = "SELECT SCOPE_IDENTITY();";
            Assert.AreEqual(expectScript, scriptEngine.GetSelectAutoIdentityScript());
        }

        #endregion

        #region Delete Script Tests
        [Test]
        public void GenerateDeleteScript()
        {
            const string expectedScript = "DELETE FROM [TableName] WHERE [ID] = 1;";
            var row = CreateRow("ID", "1");
            Assert.AreEqual(expectedScript, scriptEngine.GetDeleteScriptForRow(row));
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetDeleteScriptWithNullRowThrowsException()
        {
            scriptEngine.GetDeleteScriptForRow(null);
        }

        #endregion

        #region Helper methods

        private static Row CreateRow(string pkColName, string pkColValue)
        {
            var row = new Row(new Table("TableName", pkColName, new TestData()));
            row.AddColumn(pkColName, pkColValue);
            return row;
        }

        private static Row CreateRow()
        {
            return CreateRow("PKColumn", "1");
        }

        #endregion
    }
}